package im.yangqiang.android.ui.widget;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import im.yangqiang.android.ui.R;

/**
 * 云标签
 */
public class TagView extends RelativeLayout
{
    public static final String TAG = "TagView";

    static final float DEFAULT_LINE_MARGIN = 5;
    static final float DEFAULT_TAG_MARGIN = 5;
    static final float DEFAULT_TAG_TEXT_PADDING_LEFT = 8;
    static final float DEFAULT_TAG_TEXT_PADDING_TOP = 5;
    static final float DEFAULT_TAG_TEXT_PADDING_RIGHT = 8;
    static final float DEFAULT_TAG_TEXT_PADDING_BOTTOM = 5;
    static final float LAYOUT_WIDTH_OFFSET = 2;
    static final float DEFAULT_TAG_TEXT_SIZE = 14f;
    static final float DEFAULT_TAG_DELETE_INDICATOR_SIZE = 14f;
    static int DEFAULT_TAG_LAYOUT_COLOR = Color.GREEN;
    static int DEFAULT_TAG_TEXT_COLOR = Color.parseColor("#ffffff");
    static int DEFAULT_TAG_DELETE_INDICATOR_COLOR = Color.parseColor("#ffffff");
    static final String DEFAULT_TAG_DELETE_ICON = "×";
    static final boolean DEFAULT_TAG_IS_DELETABLE = false;

    private int mWidth;
    private int lineMargin;
    private int tagMargin;
    private int textPaddingLeft;
    private int textPaddingRight;
    private int textPaddingTop;
    private int texPaddingBottom;
    private Drawable tagBackground;
    private List<Tag> mTags = new ArrayList<>();
    private LayoutInflater mInflater;
    private OnTagClickListener mClickListener;
    private OnTagDeleteListener mDeleteListener;

    public TagView(Context context)
    {
        super(context, null);
        init(context, null, 0, 0);
    }

    public TagView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init(context, attrs, 0, 0);
    }

    public TagView(Context ctx, AttributeSet attrs, int defStyle)
    {
        super(ctx, attrs, defStyle);
        init(ctx, attrs, defStyle, defStyle);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public TagView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs, defStyleAttr, defStyleRes);
    }

    private void init(Context context, AttributeSet attrs, int defStyle, int defStyleRes)
    {
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        // get AttributeSet
        TypedArray typeArray = context.obtainStyledAttributes(attrs, R.styleable.TagView, defStyle, defStyleRes);
        this.lineMargin = (int) typeArray.getDimension(R.styleable.TagView_lineSpacingExtra, dpToPx(this.getContext(), DEFAULT_LINE_MARGIN));
        this.tagMargin = (int) typeArray.getDimension(R.styleable.TagView_tagSpacing, dpToPx(this.getContext(), DEFAULT_TAG_MARGIN));
        this.textPaddingLeft = (int) typeArray.getDimension(R.styleable.TagView_textPaddingLeft, dpToPx(this.getContext(), DEFAULT_TAG_TEXT_PADDING_LEFT));
        this.textPaddingRight = (int) typeArray.getDimension(R.styleable.TagView_textPaddingRight, dpToPx(this.getContext(), DEFAULT_TAG_TEXT_PADDING_RIGHT));
        this.textPaddingTop = (int) typeArray.getDimension(R.styleable.TagView_textPaddingTop, dpToPx(this.getContext(), DEFAULT_TAG_TEXT_PADDING_TOP));
        this.texPaddingBottom = (int) typeArray.getDimension(R.styleable.TagView_textPaddingBottom, dpToPx(this.getContext(), DEFAULT_TAG_TEXT_PADDING_BOTTOM));
        this.tagBackground = typeArray.getDrawable(R.styleable.TagView_tagBackground);
        DEFAULT_TAG_TEXT_COLOR = typeArray.getColor(R.styleable.TagView_tagTextColor, DEFAULT_TAG_TEXT_COLOR);
        DEFAULT_TAG_DELETE_INDICATOR_COLOR = typeArray.getColor(R.styleable.TagView_tagIndicatorColor, DEFAULT_TAG_DELETE_INDICATOR_COLOR);
        CharSequence[] tagTextArray = typeArray.getTextArray(R.styleable.TagView_android_entries);
        typeArray.recycle();
        mWidth = getScreenWidth(context);
        // this.setWillNotDraw(false);

        if (isInEditMode() && (tagTextArray == null || tagTextArray.length < 1))
        {
            ArrayList<Tag> tagList = new ArrayList<>();
            for (int i = 0; i < 6; ++i)
            {
                Tag tag = new Tag("TagItem" + i, tagBackground);
                if (i % 2 == 0)
                {
                    tag.isDeletable = true;
                }
                tagList.add(tag);
            }
            addTags(tagList);
        }
        addTags(tagTextArray);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        // drawTags();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        /*int width = getMeasuredWidth();
        if (width <= 0) return;
        mWidth = getMeasuredWidth();
        drawTags();*/
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        // View#onDraw is disabled in view group;
        // enable View#onDraw for view group : View#setWillNotDraw(false);
        // drawTags();
    }

    @Override
    protected void onVisibilityChanged(@NonNull View changedView, int visibility)
    {
        super.onVisibilityChanged(changedView, visibility);
    }

    @Override
    protected void onAttachedToWindow()
    {
        super.onAttachedToWindow();
    }

    private void drawTags()
    {
        if (getVisibility() != View.VISIBLE)
            return;
        // clear all tag
        removeAllViews();
        // layout padding left & layout padding right
        float total = getPaddingLeft() + getPaddingRight();
        int listIndex = 1;// List Index
        int index_bottom = 1;// The Tag to add below
        int index_header = 1;// The header tag of this line
        Tag tag_pre = null;
        for (Tag item : mTags)
        {
            final int position = listIndex - 1;
            final Tag tag = item;
            // inflate tag layout
            View tagLayout = mInflater.inflate(R.layout.custom_view_tag_view, null);
            tagLayout.setId(listIndex);
            tagLayout.setBackgroundDrawable(getSelector(tag));
            // tag text
            TextView tagView = (TextView) tagLayout.findViewById(R.id.tv_tag_item_contain);
            tagView.setText(tag.text);
            //tagView.setPadding(textPaddingLeft, textPaddingTop, textPaddingRight, texPaddingBottom);
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tagView.getLayoutParams();
            params.setMargins(textPaddingLeft, textPaddingTop, textPaddingRight, texPaddingBottom);
            tagView.setLayoutParams(params);
            tagView.setTextColor(tag.tagTextColor);
            tagView.setTextSize(TypedValue.COMPLEX_UNIT_SP, tag.tagTextSize);
            tagLayout.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    if (mClickListener != null)
                    {
                        mClickListener.onTagClick(position, tag);
                    }
                }
            });
            // calculate　of tag layout width
            float tagWidth = tagView.getPaint().measureText(tag.text) + textPaddingLeft + textPaddingRight;
            // tagView padding (left & right)
            // deletable text
            TextView deletableView = (TextView) tagLayout.findViewById(R.id.tv_tag_item_delete);
            if (tag.isDeletable)
            {
                deletableView.setVisibility(View.VISIBLE);
                deletableView.setText(tag.deleteIcon);
                int offset = dpToPx(getContext(), 2f);
                deletableView.setPadding(offset, textPaddingTop, textPaddingRight + offset, texPaddingBottom);
                /*params = (LinearLayout.LayoutParams) deletableView.getLayoutParams();
                params.setMargins(offset, textPaddingTop, textPaddingRight+offset, texPaddingBottom);
				deletableView.setLayoutParams(params);*/
                deletableView.setTextColor(tag.deleteIndicatorColor);
                deletableView.setTextSize(TypedValue.COMPLEX_UNIT_SP, tag.deleteIndicatorSize);
                deletableView.setOnClickListener(new OnClickListener()
                {
                    @Override
                    public void onClick(View v)
                    {
                        TagView.this.remove(position);
                        if (mDeleteListener != null)
                        {
                            mDeleteListener.onTagDeleted(position, tag);
                        }
                    }
                });
                tagWidth += deletableView.getPaint().measureText(tag.deleteIcon) + deletableView.getPaddingLeft() + deletableView.getPaddingRight();
                // deletableView Padding (left & right)
            } else
            {
                deletableView.setVisibility(View.GONE);
            }
            LayoutParams tagParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            //tagParams.setMargins(0, 0, 0, 0);
            //add margin of each line
            tagParams.bottomMargin = lineMargin;
            if (mWidth <= total + tagMargin + tagWidth + dpToPx(this.getContext(), LAYOUT_WIDTH_OFFSET))
            {
                //need to add in new line
                tagParams.addRule(RelativeLayout.BELOW, index_bottom);
                // initialize total param (layout padding left & layout padding right)
                total = getPaddingLeft() + getPaddingRight();
                index_bottom = listIndex;
                index_header = listIndex;
            } else
            {
                //no need to new line
                tagParams.addRule(RelativeLayout.ALIGN_TOP, index_header);
                //not header of the line
                if (listIndex != index_header)
                {
                    tagParams.addRule(RelativeLayout.RIGHT_OF, listIndex - 1);
                    tagParams.leftMargin = tagMargin;
                    total += tagMargin;
                    if (tag_pre.tagTextSize < tag.tagTextSize)
                    {
                        index_bottom = listIndex;
                    }
                }
            }
            total += tagWidth;
            addView(tagLayout, tagParams);
            tag_pre = tag;
            listIndex++;
        }
    }

    private Drawable getSelector(Tag tag)
    {
        return tag.backgroundDrawable;
//        if (tag.background != null)
//        return tag.background;
//        StateListDrawable states = new StateListDrawable();
//        GradientDrawable gd_normal = new GradientDrawable();
//        gd_normal.setColor(tag.backgroundDrawable);
//        gd_normal.setCornerRadius(tag.radius);
//        if (tag.layoutBorderSize > 0)
//        {
//            gd_normal.setStroke(dpToPx(getContext(), tag.layoutBorderSize), tag.layoutBorderColor);
//        }
//        GradientDrawable gd_press = new GradientDrawable();
//        gd_press.setColor(tag.layoutColorPress);
//        gd_press.setCornerRadius(tag.radius);
//        states.addState(new int[]{android.R.attr.state_pressed}, gd_press);
//        //must add state_pressed first，or state_pressed will not take effect
//        states.addState(new int[]{}, gd_normal);
//        return states;
    }

    public void addTag(Tag tag)
    {
        mTags.add(tag);
        drawTags();
    }

    public void addTags(String[] tags)
    {
        if (tags == null || tags.length <= 0)
            return;
        for (String item : tags)
        {
            Tag tag = new Tag(item, tagBackground);
            mTags.add(tag);
        }
        drawTags();
    }

    public void addTags(CharSequence[] textArrays)
    {
        if (textArrays == null || textArrays.length < 1)
        {
            return;
        }
        for (CharSequence charSequence : textArrays)
        {
            mTags.add(new Tag(charSequence.toString(), tagBackground));
        }
        drawTags();
    }

    public void addTags(List<Tag> tagList)
    {
        if (tagList == null || tagList.size() <= 0)
            return;
        mTags.addAll(tagList);
        drawTags();
    }

    public List<Tag> getTags()
    {
        return mTags;
    }

    public void remove(int position)
    {
        mTags.remove(position);
        drawTags();
    }

    public void removeAllTags()
    {
        mTags.clear();
        drawTags();
    }

    public int getLineMargin()
    {
        return lineMargin;
    }

    public void setLineMargin(float lineMargin)
    {
        this.lineMargin = dpToPx(getContext(), lineMargin);
    }

    public int getTagMargin()
    {
        return tagMargin;
    }

    public void setTagMargin(float tagMargin)
    {
        this.tagMargin = dpToPx(getContext(), tagMargin);
    }

    public int getTextPaddingLeft()
    {
        return textPaddingLeft;
    }

    public void setTextPaddingLeft(float textPaddingLeft)
    {
        this.textPaddingLeft = dpToPx(getContext(), textPaddingLeft);
    }

    public int getTextPaddingRight()
    {
        return textPaddingRight;
    }

    public void setTextPaddingRight(float textPaddingRight)
    {
        this.textPaddingRight = dpToPx(getContext(), textPaddingRight);
    }

    public int getTextPaddingTop()
    {
        return textPaddingTop;
    }

    public void setTextPaddingTop(float textPaddingTop)
    {
        this.textPaddingTop = dpToPx(getContext(), textPaddingTop);
    }

    public int getTexPaddingBottom()
    {
        return texPaddingBottom;
    }

    public void setTexPaddingBottom(float texPaddingBottom)
    {
        this.texPaddingBottom = dpToPx(getContext(), texPaddingBottom);
    }

    public void setOnTagClickListener(OnTagClickListener clickListener)
    {
        mClickListener = clickListener;
    }

    public void setOnTagDeleteListener(OnTagDeleteListener deleteListener)
    {
        mDeleteListener = deleteListener;
    }

    public interface OnTagClickListener
    {
        void onTagClick(int position, Tag tag);
    }

    public interface OnTagDeleteListener
    {
        void onTagDeleted(int position, Tag tag);
    }

    private int dpToPx(Context c, float dipValue)
    {
        DisplayMetrics metrics = c.getResources().getDisplayMetrics();
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics);
    }

    private int spToPx(Context context, float spValue)
    {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue, metrics);
    }

    private int getScreenWidth(Context context)
    {
        return context.getResources().getDisplayMetrics().widthPixels;
    }

    public static class Tag
    {
        private int id;
        private String text;
        private int tagTextColor;
        private float tagTextSize;
        private Drawable backgroundDrawable;
        private boolean isDeletable;
        private int deleteIndicatorColor;
        private float deleteIndicatorSize;
        private String deleteIcon;

        public Tag(String text, int color)
        {
            init(id, text, DEFAULT_TAG_TEXT_COLOR, DEFAULT_TAG_TEXT_SIZE, new ColorDrawable(color), DEFAULT_TAG_IS_DELETABLE, DEFAULT_TAG_DELETE_INDICATOR_COLOR,
                    DEFAULT_TAG_DELETE_INDICATOR_SIZE, DEFAULT_TAG_DELETE_ICON);

        }

        public Tag(String text, Drawable tagBackground)
        {
            init(id, text, DEFAULT_TAG_TEXT_COLOR, DEFAULT_TAG_TEXT_SIZE, tagBackground, DEFAULT_TAG_IS_DELETABLE, DEFAULT_TAG_DELETE_INDICATOR_COLOR,
                    DEFAULT_TAG_DELETE_INDICATOR_SIZE, DEFAULT_TAG_DELETE_ICON);

        }

        public Tag(int id, String text)
        {
            init(id, text, DEFAULT_TAG_TEXT_COLOR, DEFAULT_TAG_TEXT_SIZE, new ColorDrawable(DEFAULT_TAG_LAYOUT_COLOR), DEFAULT_TAG_IS_DELETABLE, DEFAULT_TAG_DELETE_INDICATOR_COLOR,
                    DEFAULT_TAG_DELETE_INDICATOR_SIZE, DEFAULT_TAG_DELETE_ICON);
        }

        public Tag(int id, String text, int color)
        {
            init(id, text, DEFAULT_TAG_TEXT_COLOR, DEFAULT_TAG_TEXT_SIZE, new ColorDrawable(color), DEFAULT_TAG_IS_DELETABLE, DEFAULT_TAG_DELETE_INDICATOR_COLOR,
                    DEFAULT_TAG_DELETE_INDICATOR_SIZE, DEFAULT_TAG_DELETE_ICON);

        }

        public Tag(int id, String text, Drawable tagBackground)
        {
            init(id, text, DEFAULT_TAG_TEXT_COLOR, DEFAULT_TAG_TEXT_SIZE, tagBackground, DEFAULT_TAG_IS_DELETABLE, DEFAULT_TAG_DELETE_INDICATOR_COLOR,
                    DEFAULT_TAG_DELETE_INDICATOR_SIZE, DEFAULT_TAG_DELETE_ICON);

        }

        private void init(int id, String text, int tagTextColor, float tagTextSize, Drawable tagBackground, boolean isDeletable, int deleteIndicatorColor, float
                deleteIndicatorSize, String deleteIcon)
        {
            this.id = id;
            this.text = text;
            this.tagTextColor = tagTextColor;
            this.tagTextSize = tagTextSize;
            this.backgroundDrawable = tagBackground;
            this.isDeletable = isDeletable;
            this.deleteIndicatorColor = deleteIndicatorColor;
            this.deleteIndicatorSize = deleteIndicatorSize;
            this.deleteIcon = deleteIcon;
        }
    }
}
